﻿// <copyright file="AudioSink.cs" company="Waveform Lab.NET">
// Signal processing by PC oscilloscope
// http://waveformlab.codeplex.com/
//
// Copyright (c) 2011 Waveform Lab.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
#if SILVERLIGHT
using System;
using System.Net;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;


namespace AudioModule_SL
{
    public class WaveInEventArgs : EventArgs
    {
        private byte[] buffer;
        private int bytes;

        /// <summary>
        /// Creates new WaveInEventArgs
        /// </summary>
        public WaveInEventArgs(byte[] buffer, int bytes)
        {
            this.buffer = buffer;
            this.bytes = bytes;
        }

        /// <summary>
        /// Buffer containing recorded data. Note that it might not be completely
        /// full. <seealso cref="BytesRecorded"/>
        /// </summary>
        public byte[] Buffer
        {
            get { return buffer; }
        }

        /// <summary>
        /// The number of recorded bytes in Buffer. <seealso cref="Buffer"/>
        /// </summary>
        public int BytesRecorded
        {
            get { return bytes; }
        }
    }

    public class MyAudioSink : AudioSink
    {
        private bool _enable_left = true;
        private bool _enable_right = true;
        private int _samplenumber = 0;

        public event EventHandler<WaveInEventArgs> DataAvailable;

        public MyAudioSink()
        {
        }

        public MyAudioSink(Stream outputStream)
        {
            if (outputStream == null) throw new ArgumentException("Output stream must not be null");
            if (!outputStream.CanWrite) throw new ArgumentException("Output stream must be writeable");
            OutPut = outputStream;
        }

        public Stream OutPut { get; private set; }

        protected override void OnCaptureStarted()
        {
            //throw new NotImplementedException();
        }

        protected override void OnCaptureStopped()
        {
            //throw new NotImplementedException();
        }

        protected override void OnFormatChange(AudioFormat audioFormat)
        {
            //throw new NotImplementedException();
        }

        private bool run = true;
        private int run_cnt = 0;
        private bool trigger_left = false;
        private bool trigger_right = false;
        private int off_cnt_left = 0;
        private int off_cnt_right = 0;
        private float left_in = 0.25f;
        private float left_out = 0.1f;
        private float right_in = 0.25f;
        private float right_out = 0.1f;
        private int seq_cnt = 0;
        private int seq_cnt_l = 0;
        private int seq_cnt_r = 0;
        public int seq_start_l = 0;
        public int seq_start_r = 0;
        private bool inhibit_left = false;
        private bool inhibit_right = false;
        private int off_cnt_l = 50;
        private int off_cnt_r = 200;
        private float[] mem_l;
        private float[] mem_r;
        private int mem_size = 30000;
        protected override void OnSamples(long sampleTimeInHundredNanoseconds, long sampleDurationInHundredNanoseconds, byte[] sampleData)
        {
            //OutPut.Write(sampleData, 0, sampleData.Length);
            if (DataAvailable != null)
            {
                DataAvailable(this, new WaveInEventArgs(sampleData, sampleData.Length));
            }
        }

#if !SILVERLIGHT

        private void stab()
        {
            if (run == false) return;
            else
            {
                //if (run_cnt == 0)
                //    Dispatcher.Invoke(DispatcherPriority.Normal, ((ThreadStart)delegate()
                //    { labelRun.Background = Brushes.Green; }));
                //else if (run_cnt == 50)
                //    Dispatcher.Invoke(DispatcherPriority.Normal, ((ThreadStart)delegate()
                //    { labelRun.Background = Brushes.Transparent; }));
                run_cnt++;
                if (run_cnt >= 10) run_cnt = 0;
            }

            byte[] buffer = sampleData;
            int bytesRecorded = sampleData.Length;
            _samplenumber = bytesRecorded;

            for (int index = 0; index < bytesRecorded; index += 4)
            {
                short sample_left = (short)((buffer[index + 1] << 8) | buffer[index + 0]);
                short sample_right = (short)((buffer[index + 3] << 8) | buffer[index + 2]);

                float sample32_left = sample_left / 32768f;
                float sample32_right = sample_right / 32768f;
/*
                if (index == 0)
                {
                    Dispatcher.Invoke(DispatcherPriority.Normal, ((ThreadStart)delegate()
                    {
                        progressBarLeft.Value = sample32_left;
                        progressBarRight.Value = sample32_right;
                    }));
                }
*/
                if (_enable_left)
                {
                    if (trigger_left == false)
                    {
                        if ((sample32_left > left_in) && !inhibit_left)
                        {
                            trigger_left = true;
                            seq_cnt_l = 0;
                            if (trigger_right == false) seq_cnt = 0;
                            seq_start_l = seq_cnt;
/*
                            Dispatcher.Invoke(DispatcherPriority.Normal, ((ThreadStart)delegate()
                            {
                                labelLeftTrigger.Background = Brushes.Red;
                            }));
 */
                        }
                    }
                    else
                    {
                        if ((sample32_left > -left_out) && (sample32_left < left_out))
                        {
                            off_cnt_left++;
                            if (off_cnt_left > off_cnt_l)
                            {
                                trigger_left = false;
                                if (trigger_right == false) DataWrite(seq_cnt, seq_start_l, seq_cnt_l, seq_start_r, seq_cnt_r);
                                else inhibit_left = true;
/*
                                Dispatcher.Invoke(DispatcherPriority.Normal, ((ThreadStart)delegate()
                                {
                                    labelLeftTrigger.Background = Brushes.Transparent;
                                }));
 */
                            }
                        }
                        else off_cnt_left = 0;
                    }
                }

                if (_enable_right)
                {
                    if (trigger_right == false)
                    {
                        if ((sample32_right > right_in) && !inhibit_right)
                        {
                            trigger_right = true;
                            seq_cnt_r = 0;
                            if (trigger_left == false) seq_cnt = 0;
                            seq_start_r = seq_cnt;
/*
                            Dispatcher.Invoke(DispatcherPriority.Normal, ((ThreadStart)delegate()
                            {
                                labelRightTrigger.Background = Brushes.Red;
                            }));
 */
                        }
                    }
                    else
                    {
                        if ((sample32_right > -right_out) && (sample32_right < right_out))
                        {
                            off_cnt_right++;
                            if (off_cnt_right > off_cnt_r)
                            {
                                trigger_right = false;
                                if (trigger_left == false) DataWrite(seq_cnt, seq_start_l, seq_cnt_l, seq_start_r, seq_cnt_r);
                                else inhibit_right = true;
/*
                                Dispatcher.Invoke(DispatcherPriority.Normal, ((ThreadStart)delegate()
                                {
                                    labelRightTrigger.Background = Brushes.Transparent;
                                }));
 */
                            }
                        }
                        else off_cnt_right = 0;
                    }
                }

                if (trigger_left)
                {
                    if (mem_size > seq_cnt_l)
                    {
                        mem_l[seq_cnt_l] = sample32_left;
                        seq_cnt_l++;
                    }
                    else OverMemory();
                }
                if (trigger_right)
                {
                    if (mem_size > seq_cnt_r)
                    {
                        mem_r[seq_cnt_r] = sample32_right;
                        seq_cnt_r++;
                    }
                    else OverMemory();
                }
                if ((trigger_left == true) || (trigger_right == true)) seq_cnt++;
            }
        }
#endif

        private void OverMemory()
        {
            trigger_left = false;
            trigger_right = false;
            inhibit_left = false;
            inhibit_right = false;
            DataWrite(seq_cnt, seq_start_l, seq_cnt_l, seq_start_r, seq_cnt_r);
        }

        private void DataWrite(int master, int start_l, int cnt_l, int start_r, int cnt_r)
        {
        }
    }


}

#endif
